package com.mx.spring.security.interceptor;

import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.router.SaRouteFunction;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.mx.spring.dev.code.Code;
import com.mx.spring.dev.constants.Constants;
import com.mx.spring.dev.result.MxResult;
import com.mx.spring.security.SaUtil;
import com.mx.spring.security.annotation.NoLogin;
import com.mx.spring.security.base.code.SecurityCode;
import com.mx.spring.security.base.model.SecurityUser;
import com.mx.spring.security.handler.Handler;
import com.mx.spring.security.mapper.ISecurityUserMapper;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;

public class MxSaRouteInterceptor implements HandlerInterceptor {

    private final ISecurityUserMapper iSecurityUserMapper = SpringUtil.getBean(ISecurityUserMapper.class);

    private final SaUtil saUtil = SpringUtil.getBean(SaUtil.class);

    public SaRouteFunction function = (req, res, handler) -> {
        StpUtil.checkLogin();
        SecurityUser securityUser = iSecurityUserMapper.selectById(saUtil.loginId());
        if (securityUser == null) {
            throw new NotLoginException(Code.NOT_LOGIN.code(), null, null);
        }
        if (Objects.equals(Constants.BOOL_TRUE, securityUser.getDisableStatus())) {
            throw new NotLoginException(SecurityCode.SECURITY_LOGIN_USER_DISABLE.msg(), null, null);
        }
        Handler.loginHandler().checkLoginCustom(securityUser);
    };

    /**
     * 创建一个路由拦截器
     */
    public MxSaRouteInterceptor() {
    }

    public MxSaRouteInterceptor(SaRouteFunction function) {
        this.function = function;
    }

    public static MxSaRouteInterceptor newInstance(SaRouteFunction function) {
        return new MxSaRouteInterceptor(function);
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        try {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
                NoLogin annotation = method.getAnnotation(NoLogin.class);
                if (annotation != null) {
                    return true;
                }
                annotation = method.getDeclaringClass().getAnnotation(NoLogin.class);
                if (annotation != null) {
                    return true;
                }
            }
            function.run(new SaRequestForServlet(request), new SaResponseForServlet(response), handler);
        } catch (StopMatchException e) {
            // 停止匹配，进入Controller
        } catch (BackResultException e) {
            // 停止匹配，向前端输出结果
            if (response.getContentType() == null) {
                response.setContentType("text/plain; charset=utf-8");
            }
            MxResult<?> mxResult = MxResult.create(Code.ERROR, e.getMessage());
            response.getWriter().print(mxResult.toJson());
            return false;
        }
        // 通过验证
        return true;
    }

}
